{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {
    "slideshow": {
     "slide_type": "slide"
    }
   },
   "source": [
    "# Interactive figures\n",
    "\n",
    "In addition to the static figures we have been working with, Matplotlib can produce interactive figures.  For use on a desktop there are bindings to produces figures using the Tk, Gtk, Wx, and Qt frameworks.   These can be used as stand-alone windows are embedded in large applications, see [the gallery](https://matplotlib.org/gallery/#embedding-matplotlib-in-graphical-user-interfaces) for details.\n",
    "\n",
    "There are two backends to work with IPython/Jupyter notebook:\n",
    "\n",
    " - NBAgg which ships with Matplotlib  \n",
    "   - `%matplotlib notebook`\n",
    " - ipympl which is an additional package \n",
    "   - `%matplotlib widgets`\n",
    " \n",
    " \n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "slideshow": {
     "slide_type": "skip"
    }
   },
   "source": [
    "NBAgg only works in the classic IPython notebook but not in Jupyter lab (because the way it works is by injecting a fair amount of javascript into the DOM which is a security hole).  ipympl is built on top of the `ipywidgets` framework and requires a jupyterlab extension to be installed in addition to the python module.\n",
    " \n",
    "If you are in the classic notebook\n",
    " \n",
    " ```python\n",
    "%matplotlib notebook\n",
    "```\n",
    "\n",
    "will enable NBAgg.  In either the classic notebook or jupyter lab\n",
    "\n",
    "```python\n",
    "%matplotlib widget\n",
    "```\n",
    "\n",
    "will enable ipympl."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "slideshow": {
     "slide_type": "slide"
    }
   },
   "outputs": [],
   "source": [
    "%matplotlib notebook\n",
    "import matplotlib.pyplot as plt"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "slideshow": {
     "slide_type": "slide"
    }
   },
   "outputs": [],
   "source": [
    "fig, ax = plt.subplots()\n",
    "ax.plot(range(42))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "You should now have an interactive figure that you can pan / zoom around on just like on the desktop.  Matplotlib is using a client-server model for the display, user input is sent from the Jupyter front-end back to Matplotlib running in your kernel and the kernel ships the rendered png to the browser.  This has he advantages that the plots will look identical to using `inline` or the desktop backends and we do not need to ship all of your data to the browser.  However, this approach has will have higher latency than an in-browser plotting library (such as bokeh or plotly)."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "slideshow": {
     "slide_type": "slide"
    }
   },
   "source": [
    "## print statements and tracebacks in callbacks\n",
    "\n",
    "Any print statements or tracebacks in user-callbacks will not be naively shown in the notebook (because it is not clear _where_ they should be shown; in a terminal they are printed to stdout of which there is only one, in a notebook there are many output cells, any of which may be the correct place to print).  For convince in the next few notebooks we have provided a helper to make sure that the print statements will be associated with an output area under the `Figure`."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "slideshow": {
     "slide_type": "fragment"
    }
   },
   "outputs": [],
   "source": [
    "%run helpers/ensure_print.py"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "slideshow": {
     "slide_type": "skip"
    }
   },
   "source": [
    "Understanding this code is not required for this tutorial, but running the above is required for the following notebooks to run properly.  We are discussing how to solve this in a cleaner way [at ipympl](https://github.com/matplotlib/jupyter-matplotlib/issues/116).\n",
    "\n",
    "To test that this is working, run the following cell and pan/zoom around."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "slideshow": {
     "slide_type": "slide"
    }
   },
   "outputs": [],
   "source": [
    "fig, ax = plt.subplots()\n",
    "ax.plot(range(52))\n",
    "fig.canvas.mpl_connect('draw_event', lambda event: print(\"I Drew!\"))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "celltoolbar": "Slideshow",
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.7.3"
  },
  "latex_envs": {
   "LaTeX_envs_menu_present": true,
   "autoclose": false,
   "autocomplete": true,
   "bibliofile": "biblio.bib",
   "cite_by": "apalike",
   "current_citInitial": 1,
   "eqLabelWithNumbers": true,
   "eqNumInitial": 1,
   "hotkeys": {
    "equation": "Ctrl-E",
    "itemize": "Ctrl-I"
   },
   "labels_anchors": false,
   "latex_user_defs": false,
   "report_style_numbering": false,
   "user_envs_cfg": false
  },
  "varInspector": {
   "cols": {
    "lenName": 16,
    "lenType": 16,
    "lenVar": 40
   },
   "kernels_config": {
    "python": {
     "delete_cmd_postfix": "",
     "delete_cmd_prefix": "del ",
     "library": "var_list.py",
     "varRefreshCmd": "print(var_dic_list())"
    },
    "r": {
     "delete_cmd_postfix": ") ",
     "delete_cmd_prefix": "rm(",
     "library": "var_list.r",
     "varRefreshCmd": "cat(var_dic_list()) "
    }
   },
   "types_to_exclude": [
    "module",
    "function",
    "builtin_function_or_method",
    "instance",
    "_Feature"
   ],
   "window_display": false
  }
 },
 "nbformat": 4,
 "nbformat_minor": 4
}
